﻿using PloobsEngine.SceneControl;
using PloobsEngine.Physics;
using PloobsEngine;
using PloobsEngine.Cameras;
using PloobsEngine.Input;
using Microsoft.Xna.Framework;
using PloobsEngine.Physics.Bepu;
using PloobsEngine.Modelo;
using PloobsEngine.Material;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.Commands;
using PloobsEngineDemo3;
using PloobsEngine.Light;
using PloobsEngine.Modelo.Animation;
using Microsoft.Xna.Framework.Input;

namespace Etapa1.Screens
{
    /// <summary>
    /// Screen Animacao
    /// </summary>
    public class AnimationScreen : SceneScreen
    {
        /// <summary>
        /// Mundo fisico
        /// </summary>
        private BepuPhysicWorld physicWorld;

        /// <summary>
        /// Mundo Virtual
        /// </summary>
        private BrutalForceWorld mundo;

        private EngineStuff engine;

        /// <summary>
        /// Controlador de animacao para o marine
        /// </summary>
        private AnimatedController arobo;

        /// <summary>
        /// Controlador de animacao para a aranha
        /// </summary>
        private AnimatedController abeast;

        /// <summary>
        /// Camera
        /// </summary>
        ICamera cam;

        public AnimationScreen(EngineStuff es)
        {
            this.engine = es;
            physicWorld = new BepuPhysicWorld();
            mundo = new BrutalForceWorld(physicWorld);                        
        }
        
        public override void LoadContent(EngineStuff es)
        {
            ///Chama o metodo da classe pai
            base.LoadContent(es);

            ///Adiciona o Conponent de Input
            InputAdvanced inp = new InputAdvanced(engine);
            engine.AddComponent(inp);            

            #region Models

            ///Cria o marine
            IObject marine ;
            {
                ///carrega o Modelo
                AnimatedModel am = new AnimatedModel("..\\Content\\Model\\PlayerMarine", "..\\Content\\Textures\\PlayerMarineDiffuse");
                am.LoadModelo();
                ///Inicializa o Controlador (Idle eh o nome da animacao inicial)
                arobo = new AnimatedController(am,"Idle");                                
                //arobo.ChangeInterpolationMode(AnimationInterpolationMode.Spherical_Interpolation);
                //arobo.Speed = arobo.Speed * 1.5f;
                
                ///Cria o shader e o material animados 
                SimpleAnimationShader sas = new SimpleAnimationShader(arobo);
                AnimatedMaterial amat = new AnimatedMaterial(arobo, sas);                

                ///Cria o Controlador de Input (o objeto fisico esta dentro dele)
                ///Que contem funcoes para manipular o personagem (Movimentacao)
                CharacterControllerInput character = new CharacterControllerInput(this,new Vector3(100,50,1),25,10,50);
                ///Acesse character.CharacterController para mudar como o personagem anda                
                ///Cria o Objeto Marine
                marine  = new SimpleObject(amat, character.CharacterController, am);
                ///Adiciona no mundo
                mundo.AddObject(marine);                
            }

            {
                ///carrega o Modelo (com Bump)
                AnimatedModel am = new AnimatedModel("..\\Content\\Model\\EnemyBeast", "..\\Content\\Textures\\EnemyBeastDiffuse");
                am.BumpMapName = "..\\Content\\Textures\\EnemyBeastNormal";
                am.LoadModelo();
                ///Cria o controlador
                abeast = new AnimatedController(am,"Take 001");
                ///Cria o shader de animacao (Usando bump)
                CustomAnimationShader sas = new CustomAnimationShader(abeast, true, false, false);
                ///Cria o material
                AnimatedMaterial amat = new AnimatedMaterial(abeast, sas);
                ///Cria o objeto fisico que representara o modelo
                GhostObject g = new GhostObject(new Vector3(-100, 100, -100), Matrix.Identity, Vector3.One);
                ///Cria o objeto e o adiciona no mundo
                IObject o = new SimpleObject(amat, g, am);
                mundo.AddObject(o);

            }

            {
                ///Cria a arma que sera atachada ao Marine
                AnimatedModel am = new AnimatedModel("..\\Content\\Model\\WeaponMachineGun", "..\\Content\\Textures\\WeaponMachineGunDiffuse");                
                am.LoadModelo();
                ///cria o Controlador de animacao
                AnimatedController ac = new AnimatedController(am);
                ///Cria o Shader (Observar que o nome do Bone e a instancia da Controlador de animacao do Robo eh passado como parametro)
                CustomAnimationShader sas = new CustomAnimationShader(ac, false, false, false, marine , arobo, "R_Hand2");
                ///Cria o material, o objeto e os adiciona no mundo
                AnimatedMaterial amat = new AnimatedMaterial(ac, sas);                
                IObject o = new SimpleObject(amat, new DummyPhysicObject(), am);
                mundo.AddObject(o);

            }

            ///Cria o cenario padrao de sempre ;)
            {
                SimpleModel sm = new SimpleModel("..\\Content\\Model\\cenario");
                sm.LoadModelo();
                IPhysicObject pi = new TriangleMeshObject(Vector3.Zero, sm);
                CustomDeferred shader = new CustomDeferred(false, false, false, false);
                shader.SpecularIntensity = 0;
                shader.SpecularPower = 0;
                shader.Initialize();
                IMaterial mat = new Material(shader);
                IObject obj3 = new SimpleObject(mat, pi, sm);
                mundo.AddObject(obj3);
            }
            

            #endregion
            ///Camera em primeira pessoa
            cam = new CameraFirstPerson(true);            
            cam.FarPlane = 2000;

            ///Objeto que permite atirar bolas de luzes na cena
            LightThrowBepu lt = new LightThrowBepu(mundo, engine);

            #region NormalLight
            ///Conjunto de luzes direcionais
            DirectionalLight ld1 = new DirectionalLight(Vector3.Left, Color.White);
            DirectionalLight ld2 = new DirectionalLight(Vector3.Right, Color.White);
            DirectionalLight ld3 = new DirectionalLight(Vector3.Backward, Color.White);
            DirectionalLight ld4 = new DirectionalLight(Vector3.Forward, Color.White);
            DirectionalLight ld5 = new DirectionalLight(Vector3.Down, Color.White);
            float li = 0.4f;
            ld1.LightIntensity = li;
            ld2.LightIntensity = li;
            ld3.LightIntensity = li;
            ld4.LightIntensity = li;
            ld5.LightIntensity = li;
            mundo.AddLight(ld1);
            mundo.AddLight(ld2);
            mundo.AddLight(ld3);
            mundo.AddLight(ld4);
            mundo.AddLight(ld5);
            #endregion

            ////Criacao de uma Tecnica
            DeferredRenderTechnic dr = new DeferredRenderTechnic(engine);
            //dr.isDebug = true;
            IRenderTechnic[] rt = new IRenderTechnic[] { dr };
            this.RenderTechnics = rt;

            ///Adiciona camera
            mundo.AddCamera(cam);

            ///Conecta o mundo criado com a Screen
            this.World = mundo;

            ///Envia uma mensagem para o Componente de Input (funcao botao sera chamada qd Space estiver pressionado)
            InputPlayableKeyBoard ip1 = new SimpleConcreteKeyboardInputPlayable(StateKey.DOWN, Keys.Space, botao, EntityType.TOOLS);
            BindKeyCommand mm = new BindKeyCommand(ip1, BindAction.ADD);
            CommandProcessor.getCommandProcessor().SendCommandSyncronous(mm);          

        }

        /// <summary>
        /// Funcao chamada qd Space for pressionado
        /// </summary>
        /// <param name="ipk"></param>
        public void botao(InputPlayableKeyBoard ipk)
        {
            ///Muda a animacao do Marine
            arobo.ChangeAnimation("Shoot", AnimationChangeMode.Normal);
        }        

    }
}

